//
//  YMath.m
//  yuikemall
//
//  Created by yuike6 yuike6 on 12-2-22.
//  Copyright (c) 2012年 yuike. All rights reserved.
//
#import "NSString+Extension.h"
#import "YMath.h"
#import "RegexKitLite.h"
#import "header.h"


@implementation YFloatRange
@synthesize a;
@synthesize b;
+(YFloatRange*)floatRange {
    YFloatRange* temp = [[[YFloatRange alloc] init] autorelease];
    temp.a = 0;
    temp.b = 0;
    return temp;
}
@end






@implementation YMath


+ (YFloatRange*) parseFloatRange:(NSString*)str {
    if (!str || str.strip.length<=0) {
        return [YFloatRange floatRange];
    }
    str = str.strip; // 去掉空格
    //浮点数  
    //[^(-?\\d+)(\\.\\d+)?$]　　
    NSArray* array = [str componentsMatchedByRegex:@"(-?\\d+)(\\.\\d+)?"];
    YFloatRange* retRange = [YFloatRange floatRange];
    if (array != nil) {
        if (array.count >= 1) {
            retRange.a = retRange.b = [[array objectAtIndex:0] floatValue];
        }
        if (array.count >= 2) {
            retRange.b = [[array objectAtIndex:1] floatValue];
        }
        if (retRange.a > retRange.b) {
            float temp = retRange.a;
            retRange.a = retRange.b;
            retRange.b = temp;
        }
    }
    return retRange;
}
//+ (void) parseFloatRangeTest {
//    YFloatRange* temp = [self parseFloatRange:nil];
//    temp = [self parseFloatRange:@""];
//    temp = [self parseFloatRange:@"1.2 6.8"];
//    temp = [self parseFloatRange:@"1 3.4"];
//    temp = [self parseFloatRange:@"1.1.2.4"];
//    temp = [self parseFloatRange:@"asdf3saf4.8.9asf"];
//    temp = [self parseFloatRange:@"345.8~saf.67.9"];
//    temp = [self parseFloatRange:@"1"];
//    temp = [self parseFloatRange:@"2.3"];
//    temp = [self parseFloatRange:@" 32.x3 "];
//    temp = [self parseFloatRange:@"哈哈"];
//    temp = nil;
//}



+ (int)getRandomNumber:(int)from to:(int)to {
    return(int)(from + arc4random() % (to-from+1));
}


+ (CGSize) SizeScalingProportionallyToMinimumSize : (CGSize) rect 
                                    targetSize:(CGSize) targetSize
{
    CGSize reRect = rect;
    BOOL bScaledByTargetWidth = TRUE;
    bScaledByTargetWidth = rect.width < rect.height ? TRUE : FALSE;
    
    bScaledByTargetWidth = targetSize.width > targetSize.height ? TRUE : FALSE;
    
    if (bScaledByTargetWidth)
    {
        // fit with width of target
        reRect.width = targetSize.width;
        reRect.height = (rect.height / rect.width) * reRect.width;
        
        //need zoom out
        if (reRect.height < targetSize.height)
        {
            reRect.height = targetSize.height;
            reRect.width = (rect.width / rect.height) * reRect.height;
        }
        
    }
    else
    {
        // fit with height of target
        reRect.height = targetSize.height;
        reRect.width = (rect.width / rect.height) * reRect.height;
        
        // need zoom out
        if (reRect.width < targetSize.width)
        {
            reRect.width = targetSize.width;
            reRect.height = (rect.height / rect.width) * reRect.width;
        }
    }
        
    return reRect;
    
}


//private static double triangleArea(Point pos1, Point pos2, Point pos3) {
//    double result = Math.abs((pos1.x * pos2.y + pos2.x * pos3.y + pos3.x * pos1.y
//                              - pos2.x * pos1.y - pos3.x * pos2.y - pos1.x * pos3.y) / 2.0D);
//    return result;
//}

+ (double) triangleArea:(CGPoint) point1 point2:(CGPoint) point2 point3:(CGPoint) point3
{
    double result = 0;
    result = fabs((point1.x * point2.y + 
                   point2.x * point3.y +
                   point3.x * point1.y -
                   point2.x * point1.y -
                   point3.x * point2.y -
                   point1.x * point3.y) / 2.0);
    
    return result;
}

+ (BOOL) pointIsInTriangle:(CGPoint) targetPoint 
        withTrianglePoint1:(CGPoint) trianglePoint1 
        withTrianglePoint2:(CGPoint) trianglePoint2 
        withTrianglePoint3:(CGPoint) trianglePoint3
{
    BOOL result = FALSE;
    
    double triangleArea = [YMath triangleArea:trianglePoint1 point2:trianglePoint2 point3:trianglePoint3];
    
    double area = [YMath triangleArea:targetPoint point2:trianglePoint2 point3:trianglePoint3];
    area += [YMath triangleArea:targetPoint point2:trianglePoint1 point3:trianglePoint2];
    area += [YMath triangleArea:targetPoint point2:trianglePoint1 point3:trianglePoint3];
    
    if (fabs(triangleArea - area) < 0.00001f) 
    {
        result = TRUE;
    }
    return result;
}

+ (BOOL) pointIsInEllipse:(CGPoint) targetPoint 
                 ellipseA:(CGFloat) a 
                 ellipseB:(CGFloat) b 
      isFocusPointAtXAxis:(BOOL) xAxis
              centerPoint:(CGPoint) centerPoint
{
    BOOL result = TRUE;
    
    CGPoint afterCaclePoint = CGPointMake(targetPoint.x - centerPoint.x, 
                                          targetPoint.y - centerPoint.y);
    
    if (xAxis) 
    {
        if ((((afterCaclePoint.x * afterCaclePoint.x) / (a * a)) + ((afterCaclePoint.y * afterCaclePoint.y) / (b * b))) <= 1) 
        {
            result = TRUE;
        }
        else 
        {
            result = FALSE;
        }
    }
    else 
    {
        if ((((afterCaclePoint.y * afterCaclePoint.y) / (a * a)) + ((afterCaclePoint.x * afterCaclePoint.x) / (b * b))) <= 1) 
        {
            result = TRUE;
        }
        else 
        {
            result = FALSE;
        }
    }
    
    
    return result;
}

+ (CGPoint) rotatePoint:(CGPoint) point radian:(double) radian
{
    return [self rotatePoint:point radian:radian withRotatePoint:CGPointMake(0, 0)];
}

+ (CGPoint) rotatePoint:(CGPoint) point 
                radian:(double) radian 
        withRotatePoint:(CGPoint) rotatePoint
{
    CGPoint result = point;
        
    result.x = ((point.x-rotatePoint.x)*cos(radian)-(point.y-rotatePoint.y)*sin(radian)) + rotatePoint.x;
    
    result.y = ((point.y-rotatePoint.y)*cos(radian)+(point.x-rotatePoint.x)*sin(radian)) + rotatePoint.y;
    
    return result;

}


+ (float) spaceTwoPoint:(CGPoint) point1 point2:(CGPoint) point2
{
    float result = 0.0f;
    
    result = sqrtf((point1.x - point2.x) * (point1.x - point2.x) + (point1.y - point2.y) * (point1.y - point2.y));
    
    return result;
}

+ (double) polygonAreaWithPointArray:(NSMutableArray *) points
{
    int triangleCount = [points count] - 2;
    double polygonArea = 0;
    for (int i = 0; i < triangleCount; i++) 
    {
        polygonArea += [YMath triangleArea:[[points objectAtIndex: i] CGPointValue]
                                    point2:[[points objectAtIndex: i+ 1] CGPointValue] 
                                    point3:[[points objectAtIndex: i+ 2] CGPointValue]];
    }    
    return polygonArea;

}

+ (double) polygonArea:(CGPoint) firstPoint, ...
{
    NSMutableArray * pointList = [NSMutableArray arrayWithCapacity:2];
    
    CGPoint nextPoint;
    va_list argumentList;
                
    [pointList addObject:[NSValue valueWithCGPoint:firstPoint]];
    va_start(argumentList, firstPoint);
    do {
        nextPoint = va_arg(argumentList, CGPoint);
        
        if (!isnan(nextPoint.x) && !isnan(nextPoint.y)) 
        {
            [pointList addObject:[NSValue valueWithCGPoint:nextPoint]];
        }
        else 
        {
            break;
        }
        
    } while (TRUE);
    va_end(argumentList);    

    int triangleCount = [pointList count] - 2;
    
    if (triangleCount < 1) 
    {
        return 0;
    }
    
    return [self polygonAreaWithPointArray:pointList];
}

+ (double) polygonArea:(const CGPoint[]) points count:(NSInteger)count
{
    NSMutableArray * pointList = [NSMutableArray arrayWithCapacity:2];
    
    for (int i = 0; i < count; i++) 
    {
        [pointList addObject:[NSValue valueWithCGPoint:points[i]]];
    }
    
    return [self polygonAreaWithPointArray:pointList];
}

+ (BOOL) pointIsInPolygonArea:(CGPoint) targetPoint, ...
{
    BOOL result = TRUE;
    NSMutableArray * pointList = [NSMutableArray arrayWithCapacity:2];
    
    CGPoint nextPoint;
    va_list argumentList;
    
    va_start(argumentList, targetPoint);
    do {
        nextPoint = va_arg(argumentList, CGPoint);
        
        if (!isnan(nextPoint.x) && !isnan(nextPoint.y)) 
        {
            [pointList addObject:[NSValue valueWithCGPoint:nextPoint]];
        }
        else 
        {
            break;
        }
        
    } while (TRUE);
    va_end(argumentList);    

    int triangleCount = [pointList count];
    if (triangleCount < 1) 
    {
        return 0;
    }
    
    
    double polygonArea = [YMath polygonAreaWithPointArray:pointList];
    
   
    double areas = 0;
    for (int i = 0; i < triangleCount; i++) 
    {
        areas  += [YMath triangleArea:targetPoint
                                           point2:[[pointList objectAtIndex: i] CGPointValue] 
                               point3: (i + 1 == triangleCount) ? [[pointList objectAtIndex: 0] CGPointValue] :[[pointList objectAtIndex: i + 1] CGPointValue]];
    }
    
    if (polygonArea >= areas) 
    {
        result = TRUE;
    }
    else 
    {
        result = FALSE;
    }
    
    return result;
}




+ (float) radina2Angle:(float) radina
{
    float result = 0.0f;
    
    
    result = 180 / M_PI * radina;
    return result;
}

+ (float) angle2Radina:(float) angle
{
    float result = 0.0f;
    
    
    result = M_PI / 180 * angle;
    return result;
}



+(CGPoint) crossPoint:(CGPoint) point1
               point2:(CGPoint) point2
               point3:(CGPoint) point3 
               point4:(CGPoint) point4
{
    CGPoint result = CGPointZero;
    // 二元函数通式： y=ax+b
    float a1 = (point2.y - point1.y) / (point2.x - point1.x);
    float b1 = ((point1.x * point2.y) - (point2.x * point1.y)) / (point1.x - point2.x);
    
    float a2 = (point4.y - point3.y) / (point4.x - point3.x);
    float b2 = ((point3.x * point4.y) - (point4.x * point3.y)) / (point3.x - point4.x);
    result.x = (b2 - b1) / (a1 - a2);
    result.y = a1 * result.x + b1;
    
    return result;
}
@end
